//
// Created by admin on 2024/8/15.
//

#include "Senior.h"
#include <Wire.h>
#include <OneWire.h>
#include <algorithm>

bool Senior::init(void) {
    Serial.println("AHT10 & DS18B20正在进行初始话");
    Wire.beginTransmission(AHT10_I2C_ADDRESS);
    Wire.requestFrom(AHT10_I2C_ADDRESS, 6);
    while (Wire.available())
    {
        Serial.println("AHT10 Receive Data: ");
        for (int i = 0; i < 6; i++)
        {
            _data[i] = Wire.read();
             Serial.print(_data[i],HEX);
             Serial.print(" ");
        }
        Serial.println();
        if (_data[0] & 0x08 == 0)
        {
            Serial.println("进行初始化");
            Wire.write(0xE1);
            Wire.write(0x08);
            Wire.write(0x00);
        }
        else
        {
            Serial.println("不需要初始化");

        }
    }
    byte err = Wire.endTransmission();
    if (err != 0) {
        Serial.print("AHT10 init failed ");
        Serial.println(err);
        return false;
    }
    //查找oneWire Bus上连接的所有设备
    if ( !DS18B20.search(_ds_addr)) {
        Serial.println("No DS18B20 device found");
        DS18B20.reset_search();
    }
    Serial.print("DS18B20 ADDR=");
    for (int i = 0; i < 8; i++) {
        Serial.print(_ds_addr[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
    return true;
}
/*
 * 软复位
 * */
bool Senior::reset() {
    Wire.beginTransmission(AHT10_I2C_ADDRESS);
    Wire.write(0xBA);
    return Wire.endTransmission() == 0;
}

/**
 * 返回DS18B20地址
 * @param addr
 */
void Senior::DSAddress(byte (&addr)[8]) {
    std::copy(_ds_addr, _ds_addr + 8, addr);
    Serial.print("R=");
    for (int i = 0; i < 8; i++) {
        Serial.print(_ds_addr[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
}

void Senior::requestTemperatures() {

    int HighByte, LowByte, TReading, SignBit, Tc_100;
    byte present = 0;
    byte data[12];

    DS18B20.reset();
    DS18B20.select(_ds_addr);
    DS18B20.write(0x44, 1);  // 开始转换，最后备份电源开启
    vTaskDelay(1000);
//    delay(1000);     // 也许 750 毫秒就足够了，也许不行
    // 我们可能会在这里执行 DS18B20.depower()，但重置会处理它。
//    delayMicroseconds(750);

    present = DS18B20.reset();
    DS18B20.select(_ds_addr);
    DS18B20.write(0xBE);    // 读取便签本

    Serial.print("P=");
    Serial.print(present, HEX);
    Serial.print(" ");
    for (byte i = 0; i < 9; i++) {  // 我们需要 9 个字节
        data[i] = DS18B20.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
    }
    Serial.print(" CRC=");
    Serial.print( OneWire::crc8( data, 8), HEX);
    Serial.println();

    //原始数据到C的转换
    LowByte = data[0];
    HighByte = data[1];
    TReading = (HighByte << 8) + LowByte;
    SignBit = TReading & 0x8000;  // 测试大多数 sig 位
    if (SignBit) // 负数
    {
        TReading = (TReading ^ 0xffff) + 1; // 2 的补偿
    }
    //乘以 (100 * 0.0625) 或 6.25
    Tc_100 = (6 * TReading) + TReading / 4;

    _skin_temperature = (float)Tc_100 / 100;
    if(SignBit){
        _skin_temperature = -_skin_temperature;
    }
}

/**
 * Senior::update()函数的作用是从AHT10湿度和温度传感器更新读取温度和湿度数据
 * 最后读取传感器返回的原始数据，并将其转换为温度和湿度的数值。
 */
void Senior::update() {

    uint32_t d;

    // 初始化I2C总线传输
    Wire.beginTransmission(AHT10_I2C_ADDRESS);
    // 发送测量启动命令
    Wire.write(0xAC);
    // 0x33是命令的一部分，用于湿度和温度的常规测量
    Wire.write(0x33);
    // 0x00表示不需要使用高精度模式
    Wire.write(0x00);
    // 结束传输
    Wire.endTransmission();

    // 延时等待传感器完成测量
    delay(75);
    // 请求从传感器读取6字节的数据
    Wire.requestFrom(AHT10_I2C_ADDRESS, 6);
    Wire.readBytes(_data, 6);

    // 从原始数据中提取温度值
    d = ((uint32_t)(_data[3] & 0x0F) << 16) | ((uint32_t)_data[4] << 8) | _data[5];
    // 将提取的原始温度数据转换为实际温度值，单位为摄氏度
    _temperature = (float)d * 200 / 1048576 - 50;

    // 从原始数据中提取湿度值
    d = ((uint32_t)_data[1] << 12) | ((uint32_t)_data[2] << 4) | (_data[3] >> 4);
    // 将提取的原始湿度数据转换为实际湿度值，单位为百分比
    _humidity = (float)d * 100 / 1048576;
}

float Senior::getTemperature() {
    return _temperature;
}

float Senior::getHumidity() {
    return _humidity;
}

float Senior::getSkinTemperature() {
    return _skin_temperature;
}